package com.huxiu.yd.net;


import android.text.TextUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.huxiu.yd.net.responses.BaseResponse;
import com.huxiu.yd.utils.Constants;
import com.huxiu.yd.utils.ErrorResponseException;
import com.huxiu.yd.utils.Global;
import com.huxiu.yd.utils.LogUtils;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Created by kHRYSTAL on 15/9/14:下午3:00.
 */
public class GsonRequest<T> extends Request<T> {

    private final Gson gson = new Gson();

    private final Class<T> clazz;

    private final Response.Listener<T> listener;

    private boolean needsAuthenticate;

    private Map<String, String> params = null;

    public GsonRequest(String url, int method, Class<T> clazz, boolean needsAuthenticate,
                       Map<String, String> params, Response.Listener<T> listener,
                       Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.clazz = clazz;
        this.needsAuthenticate = needsAuthenticate;
        this.listener = listener;
        this.params = getCommonMap();
        if (params != null) {
            this.params.putAll(params);
        }
    }

    @Override
    public String getCacheKey() {
        String act = params.get("act");
        return super.getCacheKey() + (TextUtils.isEmpty(act) ? "" : act);
    }

    @Override
    protected Map<String, String> getParams() throws AuthFailureError {
        return params;
    }

    @Override
    protected void deliverResponse(T response) {
        if (listener != null) {
            listener.onResponse(response);
        }
    }

    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        try {
            String ret = new String(response.data, HttpHeaderParser
                    .parseCharset(response.headers));
            for (int i = 0; i < ret.length(); i += 256) {
                int start = i;
                int end = ret.length() - 2 < i + 256 ? ret.length() - 1 : i + 256;
                LogUtils.d(ret.substring(i, end));
            }
            long timeStart = System.currentTimeMillis();
            BaseResponse b = gson.fromJson(ret, BaseResponse.class);
            if (!b.isSuccess()) {
                ErrorResponseException errorResponseException = new ErrorResponseException();
                errorResponseException.result = b.result;
                errorResponseException.data = ret;
                return Response.error(new VolleyError(b.msg, errorResponseException));
            }
            T fromJson = gson.fromJson(ret, clazz);
            long timeEnd = System.currentTimeMillis();
            LogUtils.d("parse time: " + (timeEnd - timeStart));
            return Response
                    .success(fromJson, HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
            return Response.error(new ParseError(e));
        }
    }

    private Map<String, String> getCommonMap() {
        Map<String, String> params = new LinkedHashMap<>();
        params.put("Appid", Constants.APP_ID);
        params.put("Appkey", Constants.APP_SECRET);
        params.put("mid", Global.DeviceUniqueID);
        params.put("platform", "android");
        params.put("client_ver", Global.version);
        if (needsAuthenticate && Global.user != null) {
            params.put("yd_auth", Global.user.yd_auth);
            params.put("yd_key", Global.user.yd_key);
            params.put("yd_uid", Global.user.user_id);
        }
        return params;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> params = new HashMap<>();
        params.put("Content-Type", "application/x-www-form-urlencoded");
        return params;
    }
}
